#include "vtor_buffer.h"
#include "vtor_string.h"

#ifdef __VTOR_BUFFER__


void VtorSingleBuffer_Push(VtorSingleBuffer* buf, uint8_t* inBuf, int16_t inLen)
{
	// 获取当前还剩下多少空间
	// 递增满栈
	while(inLen > 0)
	{
		uint16_t writeableLen = buf->maxLen - buf->pushIdx;
		// 写入的只能是两者中比较小的
		uint16_t curLen = inLen < writeableLen ? inLen : writeableLen;
		memcpy(buf->buf + buf->pushIdx, inBuf, curLen);
		// 上次在后面，加上长度变成在前面，认定为溢出
		if(buf->pushIdx < buf->popIdx && buf->pushIdx + curLen >= buf->popIdx)
		{
			// 溢出回调
			VtorSingleBuffer_OverflowCallback(buf);
		}
		buf->pushIdx += curLen;
		inLen -= curLen; // 减去上次剩余的，得到本次能写的
		inBuf += curLen; // 移动指针指向 下次要读取的数据
		// 写到边界，回到开头
		if(buf->pushIdx == buf->maxLen)
		{
			buf->pushIdx = 0;
		}
	}
}

int16_t VtorSingleBuffer_Pop(VtorSingleBuffer* buf, uint8_t* outBuf, int16_t expOutLen)
{
	int16_t actualOutLen = 0;
	// 如果缓冲区是空的，直接返回0
	if (buf->pushIdx == buf->popIdx) {
		return 0;
	}

	// outbuf有长度，且缓冲区有数据，才继续循环
	while (expOutLen > 0 && buf->popIdx != buf->pushIdx)
	{
		// 计算从当前popIdx到缓冲区末尾或者pushIdx的前一个位置可以读取的长度
		int16_t curLen = 0;
		if(buf->pushIdx > buf->popIdx)
		{
			curLen = buf->pushIdx - buf->popIdx;
		}
		else
		{
			curLen = buf->maxLen - buf->popIdx;
		}

		curLen = curLen < expOutLen ? curLen : expOutLen;
		memcpy(outBuf + actualOutLen, buf->buf + buf->popIdx, curLen);

		buf->popIdx += curLen;
		if (buf->popIdx == buf->maxLen)
		{
			buf->popIdx = 0; // 如果到达末尾，回到开头
		}
		
		// 修改剩余长度
		expOutLen -= curLen;
		// 记录实际读出长度
		actualOutLen += curLen;
	}
	return actualOutLen;
}




void VtorMultiBuffer_SwitchInBuf(VtorMultiBuffer* buf)
{
	buf->inBuf[buf->inBufLen] = '\0'; // 放置一个字符串截断符
	uint8_t* nextInBuf = buf->inBuf + buf->maxBufLen;
	
	// 指向出界，调整指针
	if(nextInBuf >= buf->bufArray + buf->maxBufLen * buf->bufCnt)
	{
		nextInBuf = buf->bufArray;
	}
	// 保留最新数据，丢弃历史数据
	// 跳过正在读出的数据帧，保证此帧稳定
	if(nextInBuf == buf->outBuf)
	{
		nextInBuf = nextInBuf + buf->maxBufLen;
		// 溢出回调  
		VtorMultiBuffer_OverflowCallback(buf);
		// 指向出界，调整指针
		if(nextInBuf >= buf->bufArray + buf->maxBufLen * buf->bufCnt)
		{
			nextInBuf = buf->bufArray;
		}
	}
	VtorMultiBuffer_SwitchInBufCallback(buf);
	buf->inBuf = nextInBuf;
	buf->inBufLen = 0; // 切换输入buf时，清空下标
}

void VtorMultiBuffer_SwitchOutBuf(VtorMultiBuffer* buf)
{
	buf->outBuf += buf->maxBufLen;
	// 指向出界，调整指针
	if(buf->outBuf >= buf->bufArray + buf->maxBufLen * buf->bufCnt)
	{
		buf->outBuf = buf->bufArray;
	}
	if(buf->outBuf == buf->inBuf)
	{
		VtorMultiBuffer_SwitchOutBufCallback(buf);
	}
}

void VtorMultiBuffer_Push(VtorMultiBuffer* buf, uint8_t ch)
{
	// 针对指定buf的指定位置进行塞入
	buf->inBuf[buf->inBufLen++] = ch;
	if(VtorMultiBuffer_CheckSwitchInBuf(buf))
	{
		VtorMultiBuffer_SwitchInBuf(buf);
		VtorMultiBuffer_SwitchInBufCallback(buf);
	}
}


#endif // __VTOR_BUFFER__


